home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / go32 / fs / io.c < prev    next >
C/C++ Source or Header  |  1995-03-23  |  67KB  |  2,414 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <pc.h>
  6. #include <dos.h>
  7. #include <keys.h>
  8. #include <bios.h>
  9. #include <sys/stat.h>
  10. #include "ed.h"
  11. #include "fsfuncts.h"
  12. #include "io.h"
  13. #include "serial.h"
  14. #include "syms.h"
  15.  
  16. unsigned char screen_attr;
  17. unsigned char screen_attr_normal;
  18. unsigned char screen_attr_source;
  19. unsigned char screen_attr_focus;
  20. unsigned char screen_attr_ffocus;
  21. unsigned char screen_attr_break;
  22. unsigned char screen_attr_message;
  23. unsigned char screen_attr_error;
  24. unsigned char screen_attr_resize;
  25. unsigned char screen_attr_asm;
  26. unsigned char screen_attr_help;
  27. unsigned char screen_attr_addr;
  28. unsigned char screen_attr_hot;
  29. unsigned char screen_attr_button;
  30. unsigned char screen_attr_dfocus;
  31. unsigned char st_ln_attr;
  32. char *user_screen_save, *debug_screen_save;
  33. char *read_buffer;
  34. char StatusLine[100];
  35. int cols, max_cols;
  36. int rows, max_rows;
  37.  
  38. static int escaped = 0;
  39. static int using_com_port_num;
  40. static int first_transfer = 1;
  41. static char *transfer_screen_save;
  42. static char *my_line;
  43. static char *small_line;
  44. /* ---------------------------------------------------------------------- */
  45. static unsigned int
  46. get_com (void)
  47. {
  48.   int ch;
  49.  
  50.   do {
  51.     ch = com_rx();
  52.   } while (ch == 0);
  53.   return ch;
  54. }
  55. /* ---------------------------------------------------------------------- */
  56. unsigned int
  57. getykey (void)
  58. {
  59.   if (using_com_port_num)
  60.   { unsigned int ch, ch1, ch2;
  61.     if ((ch = escaped))
  62.     { escaped = 0;
  63.       return (ch);
  64.     }
  65.     ch = get_com ();
  66.     switch (ch)
  67.     { case 0x1b:
  68.     ch1 = get_com ();
  69.     if ((char)ch1 == '[')
  70.     { ch2 = get_com ();
  71.       switch (ch2)
  72.       { case 'A':             /* ^[[A == Up       */
  73.           return K_Up;
  74.         case 'B':             /* ^[[B == Down     */
  75.           return K_Down;
  76.         case 'C':             /* ^[[C == Right    */
  77.               return K_Right;
  78.             case 'D':             /* ^[[D == Left     */
  79.               return K_Left;
  80.             case 'H':             /* ^[[H == Home     */
  81.               return K_Home;
  82.             case 'K':             /* ^[[K == End      */
  83.               return K_End;
  84.             default: 
  85.               escaped = ch1;
  86.               return (K_Escape);
  87.           }
  88.         } else               
  89.         { escaped = ch1;
  90.           return (K_Escape);
  91.         } 
  92.       case 0x0d:
  93.     return K_Return;
  94.       default:
  95.         return ch;
  96.     }
  97.   } else
  98.     return getxkey();
  99. }
  100. /* ---------------------------------------------------------------------- */
  101. static void
  102. ansi_goto (int row, int col)
  103. {
  104.   sprintf (small_line, "a[%d;%df", row + 1, col + 1);
  105.   small_line[0] = 27;
  106. }
  107. /* ---------------------------------------------------------------------- */
  108. static void
  109. ansi_color (int bg, int fg)
  110. {
  111.   int is_bold = 0, is_blink = 0;
  112.  
  113.   if (bg > 7)
  114.   { is_blink = 1;
  115.     bg &= 7;
  116.   }
  117.   if (fg > 7)
  118.   { is_bold = 1;
  119.     fg &= 7;
  120.   }
  121.   switch (bg)
  122.   { case A_blue:
  123.       bg = A_red;
  124.       break;
  125.     case A_red:
  126.       bg = A_blue;
  127.       break;
  128.     case A_brown:
  129.       bg = A_cyan;
  130.       break;
  131.     case A_cyan:
  132.       bg = A_brown;
  133.       break;
  134.   }
  135.   switch (fg)
  136.   { case A_blue:
  137.       fg = A_red;
  138.       break;
  139.     case A_red:
  140.       fg = A_blue;
  141.       break;
  142.     case A_brown:
  143.       fg = A_cyan;
  144.       break;
  145.     case A_cyan:
  146.       fg = A_brown;
  147.       break;
  148.   }
  149.   bg += 40;
  150.   fg += 30;
  151.   if (is_bold)
  152.     if (is_blink)
  153.       sprintf(small_line, "a[0;1;5;%d;%dm",bg,fg);
  154.     else
  155.       sprintf(small_line, "a[0;1;%d;%dm",bg,fg);
  156.   else
  157.     if (is_blink)
  158.       sprintf(small_line, "a[0;5;%d;%dm",bg,fg);
  159.     else
  160.       sprintf(small_line, "a[0;%d;%dm",bg,fg);
  161.   small_line[0] = 27;
  162. }
  163. /* ---------------------------------------------------------------------- */
  164. static void
  165. screen_goto (int row, int col)
  166. {  
  167.   ansi_goto (row, col);
  168.   com_txs (small_line);
  169. }
  170. /* ---------------------------------------------------------------------- */
  171. void
  172. screen_scroll (int lines)
  173. {  
  174.   int i;
  175.  
  176.   screen_goto (rows, 0);
  177.   for (i = 0; i < lines; i++)
  178.     com_tx (10);
  179.   screen_goto (0, 0);
  180. }
  181. /* ---------------------------------------------------------------------- */
  182. void
  183. put (int x, int y, unsigned char *txt)
  184. {
  185.   unsigned char *p
  186.     = (unsigned char *)(debug_screen_save + 3) + 2 * (max_cols * y + x);
  187.   while (*txt)
  188.     *p++ = *txt++,
  189.     *p++ = screen_attr;
  190. }
  191. /* ---------------------------------------------------------------------- */
  192. void
  193. putl (int x, int y, int l, unsigned char *txt)
  194. {
  195.   unsigned char *p
  196.     = (unsigned char *)(debug_screen_save + 3) + 2 * (max_cols * y + x);
  197.   while (*txt && l > 0)
  198.     *p++ = *txt++,
  199.     *p++ = screen_attr,
  200.     l--;
  201.   while (l-- > 0)
  202.     *p++ = ' ',
  203.     *p++ = screen_attr;
  204. }
  205. /* ---------------------------------------------------------------------- */
  206. void
  207. clear_screen (void)
  208. {
  209.   int l = rows * max_cols;
  210.  
  211.   unsigned char *p
  212.     = (unsigned char *)(debug_screen_save + 3);
  213.   while (l-- > 0)
  214.     *p++ = ' ',
  215.     *p++ = screen_attr;
  216. }
  217. /* ---------------------------------------------------------------------- */
  218. void
  219. draw (int x, int y, unsigned char ch, int delta, int count)
  220. {
  221.   short unsigned *p
  222.     = (short unsigned *)(debug_screen_save + 3) + (max_cols * y + x);
  223.   short unsigned attrch = ((unsigned)screen_attr << 8) + ch;
  224.   while (count--)
  225.     *p = attrch,
  226.     p += delta;
  227. }
  228. /* ---------------------------------------------------------------------- */
  229. void
  230. highlight (int x, int y, int len)
  231. {
  232.   unsigned short *p
  233.     = (unsigned short *)(debug_screen_save + 4) + (max_cols * y + x);
  234.   while (len--)
  235.     *(unsigned char *)p = screen_attr,
  236.     p++;
  237. }
  238. /* ---------------------------------------------------------------------- */
  239. void
  240. frame (int x1, int y1, int x2, int y2, char *tittle)
  241. {
  242.   if (!using_com_port_num)
  243.   { draw (x1 + 1, y1, '─', 1,    x2 - x1 - 1);
  244.     draw (x1 + 1, y2, '─', 1,    x2 - x1 - 1);
  245.     draw (x1, y1 + 1, '│', max_cols, y2 - y1 - 1);
  246.     draw (x2, y1 + 1, '│', max_cols, y2 - y1 - 1);
  247.     put (x1, y1, "┌");
  248.     put (x2, y1, "┐");
  249.     put (x1, y2, "└");
  250.     put (x2, y2, "┘");
  251.   } else
  252.   { draw (x1 + 1, y1, '-', 1,    x2 - x1 - 1);
  253.     draw (x1 + 1, y2, '-', 1,    x2 - x1 - 1);
  254.     draw (x1, y1 + 1, '|', max_cols, y2 - y1 - 1);
  255.     draw (x2, y1 + 1, '|', max_cols, y2 - y1 - 1);
  256.     put (x1, y1, "+");
  257.     put (x2, y1, "+");
  258.     put (x1, y2, "+");
  259.     put (x2, y2, "+");
  260.   }                                                
  261.   if (tittle)
  262.   { int t_start, t_end;
  263.     
  264.     t_start = (x2 - x1 - 3 - strlen (tittle)) / 2;
  265.     if (t_start <= 2)
  266.     { t_start = 2;
  267.       t_end = x2 - x1 - 3;
  268.     } else
  269.       t_end = t_start + strlen (tittle) + 1;
  270.     draw (x1 + t_start, y1, '>', 1 , 1);
  271.     putl (x1 + t_start + 1, y1, t_end - t_start - 1, tittle);
  272.     draw (x1 + t_end, y1, '<', 1, 1);
  273.   }
  274. }
  275. /* ---------------------------------------------------------------------- */
  276. void
  277. double_frame (int x1, int y1, int x2, int y2, char *tittle)
  278. {
  279.   if (!using_com_port_num)
  280.   { draw (x1 + 1, y1, '═', 1,    x2 - x1 - 1);
  281.     draw (x1 + 1, y2, '═', 1,    x2 - x1 - 1);
  282.     draw (x1, y1 + 1, '║', max_cols, y2 - y1 - 1);
  283.     draw (x2, y1 + 1, '║', max_cols, y2 - y1 - 1);
  284.     put (x1, y1, "╔");
  285.     put (x2, y1, "╗");
  286.     put (x1, y2, "╚");
  287.     put (x2, y2, "╝");
  288.   } else
  289.   { draw (x1 + 1, y1, '=', 1,    x2 - x1 - 1);
  290.     draw (x1 + 1, y2, '=', 1,    x2 - x1 - 1);
  291.     draw (x1, y1 + 1, '[', max_cols, y2 - y1 - 1);
  292.     draw (x2, y1 + 1, ']', max_cols, y2 - y1 - 1);
  293.     put (x1, y1, "*");
  294.     put (x2, y1, "*");
  295.     put (x1, y2, "*");
  296.     put (x2, y2, "*");
  297.   }
  298.   if (tittle)
  299.   { int t_start, t_end;
  300.     
  301.     t_start = (x2 - x1 - 3 - strlen (tittle)) / 2;
  302.     if (t_start <= 2)
  303.     { t_start = 2;
  304.       t_end = x2 - x1 - 3;
  305.     } else
  306.       t_end = t_start + strlen (tittle) + 1;
  307.     draw (x1 + t_start, y1, '>', 1 , 1);
  308.     putl (x1 + t_start + 1, y1, t_end - t_start - 1, tittle);
  309.     draw (x1 + t_end, y1, '<', 1, 1);
  310.   }
  311. }
  312. /* ---------------------------------------------------------------------- */
  313. static void
  314. get_line (char *screen, int line_num)
  315. {
  316.   int i;
  317.   char *p2;
  318.   unsigned char *p =
  319.     (unsigned char *)(screen + 3) + 2 * max_cols * line_num;
  320.  
  321.   p2 = my_line;
  322.   i = cols * 2;
  323.   while (i)
  324.   {
  325.     *p2++ = *p++;
  326.     i--;
  327.   }        
  328.   *p2++ = 0;
  329. }
  330. /* ---------------------------------------------------------------------- */
  331. static void
  332. put_line (char *screen, char *full_line, int line_num)
  333. {
  334.   unsigned char *p =
  335.     (unsigned char *)(screen + 3) + 2 * max_cols * line_num;
  336.   char *oneline = full_line;
  337.   int i = cols * 2;
  338.  
  339.   while (i)
  340.   {
  341.     *p++ = *oneline++;
  342.     i--;
  343.   }
  344. }
  345. /* ---------------------------------------------------------------------- */
  346. static void
  347. get_differ (char *first_line, char *second_line)
  348. {
  349.   char *line_one = first_line, *line_two = second_line;
  350.   char ch1_attr, ch1_ascii, ch2_attr, ch2_ascii;
  351.   int len, i = 0;
  352.  
  353.   len = 1;
  354.   my_line[0] = '\0';
  355.  
  356.   while (i < cols)
  357.   { ch1_ascii = *line_one++;
  358.     ch1_attr  = *line_one++;
  359.     ch2_ascii = *line_two++;
  360.     ch2_attr  = *line_two++;
  361.     i++;
  362.  
  363.     if ((ch1_ascii != ch2_ascii) || (ch1_attr != ch2_attr))
  364.     { len += 5;
  365.       my_line[len - 6] = 255;
  366.       my_line[len - 5] = 255;
  367.       my_line[len - 4] = (unsigned char)i;
  368.       my_line[len - 3] = ch2_ascii;
  369.       my_line[len - 2] = ch2_attr;
  370.       my_line[len - 1] = '\0';
  371.       while (i < cols)
  372.       {    ch1_ascii = *line_one++;
  373.     ch1_attr  = *line_one++;
  374.     ch2_ascii = *line_two++;
  375.     ch2_attr  = *line_two++;
  376.     i++;
  377.  
  378.     if ((ch1_ascii == ch2_ascii) && (ch1_attr == ch2_attr))
  379.       break;
  380.  
  381.     len += 2;
  382.     my_line[len - 3] = ch2_ascii;
  383.     my_line[len - 2] = ch2_attr;
  384.     my_line[len - 1] = '\0';
  385.       }
  386.     }
  387.   }
  388. }
  389. /* ---------------------------------------------------------------------- */
  390. static int
  391. com_filter (int old_char)
  392. { old_char &= 0x7f;
  393.   switch (old_char)
  394.   { case 27:           /* ESC             */
  395.       return 27;
  396.     case 30:           /* Big Up Arrow    */
  397.       return (int)('^');
  398.     case 31:           /* Big Down Arrow  */
  399.       return (int)('v');
  400.     case 127:          /* DEL             */
  401.       return (int)('.');
  402.     default:
  403.       return (old_char < 32) ? '.' : old_char;
  404.   }
  405. }
  406. /* ---------------------------------------------------------------------- */
  407. static void
  408. line_to_ansi (char *full_line, int line_num)
  409. {
  410.   int i = cols, len;
  411.   unsigned char old_attr = 0, ch_attr, ch_ascii;
  412.   char *oneline = full_line;
  413.  
  414.   ansi_goto (line_num, 0);           
  415.   sprintf (my_line, small_line);
  416.   len = strlen (small_line);
  417.  
  418.   while (i)
  419.   { ch_ascii = *oneline++;
  420.     ch_attr  = *oneline++;
  421.  
  422.     if (old_attr != ch_attr)
  423.     { old_attr = ch_attr;
  424.       ansi_color (ch_attr >> 4, ch_attr & 0x0f);
  425.       sprintf ((char *)(my_line + len), small_line);
  426.       len += strlen (small_line);
  427.     }
  428.     my_line[len] = com_filter (ch_ascii);
  429.     my_line[++len] = '\0';
  430.     i--;
  431.   }
  432. }
  433. /* ---------------------------------------------------------------------- */
  434. static void
  435. diff_to_ansi (unsigned char *diff_line, int line_num)
  436. {
  437.   char *oneline = diff_line;
  438.   int i = 0, len = 0, dif_len = strlen(oneline);
  439.   char old_attr = 0, ch_attr = 0, ch_ascii = 0;
  440.   int is_pos = 0, pos = 0;
  441.   unsigned char char_one, char_two;
  442.  
  443.   while (i < dif_len)
  444.   { char_one = *oneline++;
  445.     char_two = *oneline++;
  446.     i += 2;
  447.     if ((char_one == 255) && (char_two == 255))
  448.     { pos = *oneline;
  449.       if (pos <= cols)
  450.       {    i++;
  451.     oneline++;
  452.     is_pos = 1;
  453.     pos--;
  454.       }
  455.       else
  456.       { ch_ascii = char_one;
  457.         ch_attr  = char_two;
  458.       }
  459.     }
  460.     else
  461.     { ch_ascii = char_one;
  462.       ch_attr  = char_two;
  463.     }
  464.  
  465.     if (is_pos)
  466.     { ansi_goto (line_num, pos);
  467.       sprintf ((char *)(my_line + len), small_line); 
  468.       len += strlen (small_line);
  469.       is_pos = 0;
  470.     }
  471.     else
  472.     { if (old_attr != ch_attr)
  473.       {    old_attr = ch_attr;
  474.     ansi_color (ch_attr >> 4, ch_attr & 0x0f);
  475.         sprintf ((char *)(my_line + len), small_line);
  476.         len += strlen (small_line);
  477.       }
  478.       my_line[len] = com_filter(ch_ascii);
  479.       my_line[++len] = '\0';
  480.     }
  481.   }
  482. }
  483. /* ---------------------------------------------------------------------- */
  484. static char new_line[1024] , old_line[1024];
  485. static char diff_line[1024], ansi_line[1024];
  486. /* ---------------------------------------------------------------------- */
  487. static void
  488. transfer_screen (char *screen)
  489. {
  490.   int line_num;         
  491.  
  492.   if (first_transfer)
  493.   { screen_scroll (rows);
  494.     line_num = 0;
  495.     do 
  496.     { get_line(screen, line_num);
  497.       put_line(transfer_screen_save, my_line, line_num);
  498.       strcpy (new_line, my_line);
  499.       line_to_ansi (new_line , line_num);
  500.       strcpy(ansi_line, my_line);
  501.       com_txs (ansi_line);
  502.     } while (++line_num < rows);
  503.     first_transfer = 0;
  504.     return;
  505.   }
  506.  
  507.   line_num = 0;
  508.   do 
  509.   { get_line(screen, line_num);
  510.     strcpy(new_line, my_line);
  511.     get_line(transfer_screen_save, line_num);
  512.     strcpy(old_line, my_line);
  513.  
  514.     if (strncmp (new_line, old_line, cols * 2))
  515.     { put_line(transfer_screen_save, new_line, line_num);
  516.       get_differ (old_line, new_line);
  517.       strcpy(diff_line, my_line);
  518.       diff_to_ansi (diff_line, line_num);
  519.       strcpy(ansi_line, my_line);
  520.       line_to_ansi (new_line , line_num);
  521.       strcpy(diff_line, my_line);
  522.       if ((strlen (ansi_line) < strlen (diff_line)))
  523.     com_txs (ansi_line);
  524.       else
  525.     com_txs (diff_line);
  526.     }
  527.  
  528.     line_num++;
  529.   } while (line_num < rows);
  530. }
  531. /* ---------------------------------------------------------------------- */
  532. static void
  533. recieve_screen (unsigned char *screen)
  534. {
  535.   unsigned char *p2 = (unsigned char *)(screen + 3);
  536.   unsigned char *p  = (unsigned char *)(transfer_screen_save + 3);
  537.   int i = max_rows * max_cols * 2;
  538.  
  539.   while (i)
  540.   {
  541.     *p2++ = *p++;
  542.     i--;
  543.   }
  544. }
  545. /* ---------------------------------------------------------------------- */
  546. void
  547. put_screen (char *screen)
  548. {
  549.   if (using_com_port_num)
  550.     transfer_screen(screen);
  551.   else
  552.     switch (*screen++)
  553.       {
  554.       case 0:
  555.     /* Text screen.  */
  556.     ScreenSetCursor (screen[0], screen[1]);
  557.     ScreenUpdate (screen + 2);
  558.     break;
  559.       }
  560. }
  561. /* ---------------------------------------------------------------------- */
  562. char *
  563. get_screen ()
  564. {
  565.   char *p;
  566.   int r, c;
  567.  
  568.   p = malloc (max_cols * max_rows * 2 + 3);    /* Was cols * rows * ... */
  569.   if (using_com_port_num)
  570.     {
  571.       if (transfer_screen_save)
  572.     recieve_screen (p);
  573.       else
  574.         for (r = 0; r < max_rows; r++)
  575.           for (c = 0; c < max_cols; c++)
  576.           { p[2 * (r * max_cols + c) + 3] = ' ';
  577.             p[2 * (r * max_cols + c) + 4] = screen_attr;
  578.           }
  579.     }
  580.   else
  581.     {
  582.       ScreenGetCursor (&r, &c);
  583.       p[0] = 0;
  584.       p[1] = r;
  585.       p[2] = c;
  586.       ScreenRetrieve (p + 3);
  587.     }
  588.   return p;
  589. }
  590. /* ---------------------------------------------------------------------- */
  591. char *
  592. get_old_screen()
  593. {
  594.   char *saved;
  595.  
  596.   saved = debug_screen_save;
  597.   debug_screen_save = get_screen();
  598.   return saved;
  599. }
  600. /* ---------------------------------------------------------------------- */
  601. void
  602. restore_screen(char *saved)
  603. {
  604.   free (debug_screen_save);
  605.   debug_screen_save = saved;
  606. }
  607. /* ---------------------------------------------------------------------- */
  608. void
  609. refresh()
  610. {
  611.   put_screen (debug_screen_save);
  612. }
  613. /* ---------------------------------------------------------------------- */
  614. /* Reportedly, `sleep' & `gettimeofday' are buggy under Dpmi -- emulate.  */
  615. int
  616. mysleep (int secs)
  617. {
  618.   struct time now;
  619.   unsigned now100, then100;
  620.  
  621.   gettime (&now);
  622.   then100
  623.     = ((now.ti_hour * 60 + now.ti_min) * 60 + now.ti_sec + secs) * 100
  624.       + now.ti_hund;
  625.   do
  626.     {
  627.       gettime (&now);
  628.       now100 = ((now.ti_hour * 60 + now.ti_min) * 60 + now.ti_sec) * 100
  629.     + now.ti_hund;
  630.       if (now100 < 100)
  631.     break; /* Day turnover */
  632.       if (using_com_port_num)
  633.       { if (get_com ())
  634.           break;
  635.       }
  636.       else
  637.         if (bioskey (1))
  638.           break;
  639.     }
  640.   while (now100 < then100);
  641.   return 0;
  642. }
  643. /* ---------------------------------------------------------------------- */
  644. int
  645. short_sleep (unsigned long msecs)
  646. {
  647.   struct time now;
  648.   unsigned long now100, then100;
  649.  
  650.   gettime (&now);
  651.   then100
  652.     = ((now.ti_hour * 60 + now.ti_min) * 60 + now.ti_sec) * 100
  653.       + now.ti_hund + msecs;
  654.   do
  655.     {
  656.       gettime (&now);
  657.       now100 = ((now.ti_hour * 60 + now.ti_min) * 60 + now.ti_sec) * 100
  658.     + now.ti_hund;
  659.       if (now100 < 100 || bioskey (1))
  660.     break; /* Day turnover */
  661.     }
  662.   while (now100 < then100);
  663.   if (bioskey(1))
  664.     return 1;
  665.   return 0;
  666. }
  667. /* ---------------------------------------------------------------------- */
  668. /* Display a message in CLASS using FMT and ... as printf parameters.
  669.    The class determines the colour of the message and for how long time
  670.    it is displayed.  */
  671. void
  672. message (CL_TYPE class, char *fmt, ...)
  673. { int space_len;
  674.                 
  675.   vsprintf (StatusLine, fmt, (&fmt) + 1);
  676.   space_len = (cols  - strlen (StatusLine)) / 2;
  677.   sprintf (StatusLine, "%-50s", " ");
  678.   vsprintf (StatusLine + space_len, fmt, (&fmt) + 1);
  679.   switch (class)
  680.   { case CL_Error:
  681.       st_ln_attr = screen_attr_error;
  682.       break;
  683.     default:
  684.       st_ln_attr = screen_attr_message;
  685.   } 
  686.   redraw (0);
  687. }
  688. /* ---------------------------------------------------------------------- */
  689. static int
  690. input_string (int x, int y, int len, int *lastkey)
  691. { int key, esc = 0, pos, leave = 0;
  692.   int more_left = 0, insert_mode = 1, buf_len;
  693.   char *orig_str = strdup (read_buffer);
  694.   char *temp = alloca (4096);
  695.   
  696.   pos = strlen (read_buffer);              
  697.   do
  698.   { draw (x, y, ' ', 1, len);
  699.     putl (x, y, len, read_buffer + more_left);
  700.     buf_len = strlen (read_buffer);
  701.     put_screen (debug_screen_save);
  702.     if (using_com_port_num)
  703.       screen_goto (y, x + pos);
  704.     else
  705.       ScreenSetCursor (y, x + pos);
  706.     if (*lastkey)
  707.     { key = *lastkey;
  708.       *lastkey = 0;
  709.     } else
  710.       key = getykey ();
  711.     switch (key)
  712.     { case K_Up:
  713.       case K_EUp:
  714.       case K_Down:
  715.       case K_EDown:
  716.       case K_Tab:
  717.       case K_BackTab:
  718.       case K_Control_N:
  719.       case K_Control_P:
  720.         *lastkey = key;                                   /* Fall through */
  721.       case K_Return:
  722.         leave = 1;
  723.         esc = 0;
  724.         break;
  725.     case K_Escape:
  726.         key = getykey ();
  727.         if (key != K_Escape)
  728.         { *lastkey = key;                                 /* Wrong, reuse */
  729.           break;
  730.         }                                            /* Else fall through */
  731.       case K_Control_G:
  732.         leave = 1;
  733.         esc = 1;
  734.         *lastkey = K_Control_G;                      /* So ESC ESC == C-g */
  735.         strcpy (read_buffer, orig_str);
  736.         break;
  737.       case K_Control_X:
  738.         key = getykey ();
  739.         switch (key)
  740.         { case K_Control_O:
  741.           case K_Control_T:
  742.             insert_mode = !insert_mode;
  743.             break;
  744.         }
  745.         break;
  746.       case K_Insert:
  747.       case K_EInsert:
  748.         insert_mode = !insert_mode;
  749.         break;
  750.       case K_Delete:
  751.       case K_EDelete:
  752.         if (pos > 0 || more_left)
  753.         { strcpy (temp, read_buffer + (pos + more_left) * sizeof (char));
  754.           if (pos + more_left == buf_len)
  755.           { pos--;
  756.             read_buffer[pos + more_left] = '\0';
  757.             if (pos < 0)
  758.             { pos++;
  759.               more_left--;
  760.             }
  761.           } else
  762.           { strcpy (read_buffer + (pos + more_left - 1) * sizeof (char), temp);
  763.             if (more_left)
  764.               more_left--;
  765.             else
  766.               pos--;
  767.           }
  768.         }
  769.         break;
  770.       case K_Control_D:
  771.         if (pos + more_left < buf_len)
  772.         { strcpy (temp, read_buffer + (pos + more_left + 1) * sizeof (char));
  773.           strcpy (read_buffer + (pos + more_left) * sizeof (char), temp);
  774.         }
  775.         break;
  776.       case K_Left:
  777.       case K_ELeft:
  778.       case K_Control_B:
  779.         if (more_left)
  780.           more_left--;
  781.         else if (pos)
  782.           pos--;
  783.         break;
  784.       case K_Right:
  785.       case K_ERight:
  786.       case K_Control_F:
  787.         if (pos + more_left < buf_len)
  788.         { pos++;
  789.           if (pos == len)
  790.           { more_left++;
  791.             pos--;
  792.           }
  793.         }
  794.         break;
  795.       default:
  796.         if (key >= ' ' && key <= 0xff)
  797.         { if (insert_mode)
  798.             strcpy (temp, read_buffer + (pos + more_left) * sizeof (char));
  799.           read_buffer[pos + more_left] = key & 0xff;
  800.           pos++;
  801.           if (insert_mode)
  802.             strcpy (read_buffer + (pos + more_left) * sizeof (char), temp);
  803.           if (pos + more_left == buf_len)
  804.             read_buffer[buf_len] = '\0';
  805.           if (pos == len)
  806.           { more_left++;
  807.             pos--;
  808.           }
  809.         }
  810.     }
  811.   } while (!leave);
  812.   put_screen (debug_screen_save);
  813.   return esc;
  814. }
  815. /* ---------------------------------------------------------------------- */
  816. /* Read a string from the keyboard to `read_buffer'.  The entry is started
  817.    with STARTTEXT.  */
  818. int
  819. read_string (char *starttext)
  820. { char *save;
  821.   int result, temp;
  822.   
  823.   strcpy (read_buffer, starttext);
  824.   save = debug_screen_save;
  825.   debug_screen_save = get_screen ();
  826.   screen_attr = screen_attr_focus;
  827.   put (0, rows - 1, "Input: ");
  828.   do
  829.   { temp = 0;
  830.     result = input_string (7, rows - 1, cols - 7, &temp);
  831.   } while (temp && !result);
  832.   free (debug_screen_save);
  833.   debug_screen_save = save;
  834.   put_screen (debug_screen_save);
  835.   return (result);
  836. }
  837. /* ---------------------------------------------------------------------- */
  838. int
  839. my_read_string (char *prompt)
  840. { char *save;
  841.   int result, temp;
  842.   int prompt_len = strlen(prompt);
  843.  
  844.   *read_buffer = '\0';
  845.   save = debug_screen_save;
  846.   debug_screen_save = get_screen ();
  847.   screen_attr = screen_attr_focus;
  848.   put (0, rows - 1, prompt);
  849.   do
  850.   { temp = 0;
  851.     result = input_string (prompt_len, rows - 1, cols - prompt_len, &temp);
  852.   } while (temp && !result);
  853.   free (debug_screen_save);
  854.   debug_screen_save = save;
  855.   put_screen (debug_screen_save);
  856.   return (result);
  857. }
  858. /* ---------------------------------------------------------------------- */
  859. int
  860. my_get_char (char *prompt)
  861. { char *save, key[2];
  862.   int prompt_len = strlen(prompt);
  863.  
  864.   save = debug_screen_save;
  865.   debug_screen_save = get_screen ();
  866.   screen_attr = screen_attr_focus;
  867.   key[1] = 0;
  868.   draw (0, rows - 1, ' ', 1, cols);
  869.   put (0, rows - 1, prompt);
  870.   put_screen (debug_screen_save);
  871.   if (using_com_port_num)
  872.     screen_goto (rows - 1, prompt_len);
  873.   else
  874.     ScreenSetCursor (rows - 1, prompt_len);
  875.   key[0] = getykey ();
  876.   put (prompt_len, rows - 1, key); 
  877.   put_screen (debug_screen_save);
  878.   free (debug_screen_save);
  879.   debug_screen_save = save;
  880.   put_screen (debug_screen_save);
  881.   return key[0];
  882. }
  883. /* ---------------------------------------------------------------------- */
  884. int                                                     /* 1 == y, 0 == n */
  885. confirm (char *prompt)
  886. { int key = my_get_char (prompt);
  887.   if (key == 'y' || key == 'Y')
  888.     return (1);
  889.   return (0);
  890. }
  891. /* ---------------------------------------------------------------------- */
  892. void 
  893. format_addr (char *output, char *input)
  894. { char *name;
  895.   int32 delta;
  896.   word32 addr; 
  897.   int ok;
  898.   
  899.   addr = parse_expression (4, input, &ok);
  900.   name = syms_val2name (addr, &delta);
  901.   if (name[0] != '0')
  902.     if (delta)
  903.       sprintf (output, "%s+%#lx", name, delta);
  904.     else
  905.       sprintf (output, "%s", name);
  906.   else
  907.     sprintf(output,"0x%08lx",addr);
  908.   strcpy (input, output);
  909. }
  910. /* ---------------------------------------------------------------------- */
  911. void 
  912. format_word (char *output, char *input)
  913. { word32 temp = syms_name2val (input);
  914.   sprintf (output, "0x%08lx", temp);
  915.   strcpy (input, output);
  916. }
  917. /* ---------------------------------------------------------------------- */
  918. void 
  919. format_deci (char *output, char *input)
  920. { word32 temp = syms_name2val (input);
  921.   sprintf (output, "%ld", temp);
  922.   strcpy (input, output);
  923. }
  924. /* ---------------------------------------------------------------------- */
  925. void 
  926. format_int  (char *output, char *input)
  927. { word32 temp = syms_name2val (input);
  928.   sprintf (output, "%ld", temp);
  929.   strcpy (input, output);
  930. }
  931. /* ---------------------------------------------------------------------- */
  932. void 
  933. format_asis (char *output, char *input)
  934. { strcpy (output, input);
  935. }
  936. /* ---------------------------------------------------------------------- */
  937. void 
  938. eval_word   (void   *output, char *input)
  939. { int ok;
  940.   word32 *out = (word32 *)output;
  941.   *out = parse_expression (4, input, &ok);
  942. }
  943. /* ---------------------------------------------------------------------- */
  944. void 
  945. eval_asis   (void   *output, char *input)
  946. { char *temp = (char *)output;
  947.   strcpy (temp, input);
  948. }
  949. /* ---------------------------------------------------------------------- */
  950. void
  951. init_addr   (char *output, char *input, word32 addr)
  952. { sprintf (input, "0x%08lx", *(word32 *)addr);
  953.   format_addr (output, input);
  954. }
  955. /* ---------------------------------------------------------------------- */
  956. void
  957. init_word   (char *output, char *input, word32 addr)
  958. { sprintf (output, "0x%08lx", *(word32 *)addr);
  959.   strcpy (input, output);
  960. }
  961. /* ---------------------------------------------------------------------- */
  962. void
  963. init_deci   (char *output, char *input, word32 addr)
  964. { sprintf (output, "%ld", *(word32 *)addr);
  965.   strcpy (input, output);
  966. }
  967. /* ---------------------------------------------------------------------- */
  968. void
  969. init_int    (char *output, char *input, word32 addr)
  970. { sprintf (output, "%ld", *(long *)addr);
  971.   strcpy (input, output);
  972. }
  973. /* ---------------------------------------------------------------------- */
  974. void
  975. init_asis   (char *output, char *input, word32 addr)
  976. { strcpy (output, (char *)addr);
  977.   strcpy (input, output);
  978. }
  979. /* ---------------------------------------------------------------------- */
  980. int
  981. editor      (char *text, word32 addr, int x, int y, int len, int *key)
  982. { strcpy (read_buffer, text);
  983.   return (input_string (x, y, len, key));
  984. }
  985. /* ---------------------------------------------------------------------- */
  986. int
  987. action_done (DIALOG_ITEM dialog_data[])
  988. { return (1);
  989. }
  990. /* ---------------------------------------------------------------------- */
  991. void 
  992. dialog (char *tittle,
  993.         DIALOG_ITEM dialog_data[], BUTTON_ITEM button_data[], int *ret)
  994. { char *save, **buffer, **inputs;
  995.   int key = 0, pos, leave = 0, editable = 0;
  996.   int x1 = 1, x2 = cols - x1 - 1;
  997.   int y1, y2, max_field_len = 0, max_button_len = 0;
  998.   int i, items, buttons, len = 0, x_button, width;
  999.                                  
  1000.   for (i = 0; dialog_data[i].field_name; i++)
  1001.   { len = strlen (dialog_data[i].field_name);
  1002.     if (len > max_field_len)
  1003.       max_field_len = len;             
  1004.     if (dialog_data[i].editable)
  1005.       editable = 1;
  1006.   }                
  1007.   width = x2 - x1 - max_field_len - 3;
  1008.   items = i;          
  1009.   for (i = 0; button_data[i].name; i++)
  1010.   { len = strlen (button_data[i].name);
  1011.     if (len > max_button_len)
  1012.       max_button_len = len;
  1013.     editable = 1;
  1014.   }                    
  1015.   buttons = i;
  1016.   max_button_len += 2;                    
  1017.   if (!editable)
  1018.   { *ret = 0;
  1019.     return;    
  1020.   }
  1021.   buffer = malloc (items * sizeof (char *));                             
  1022.   inputs = malloc (items * sizeof (char *));                             
  1023.   for (i = 0; i < items; i++)
  1024.   { if (dialog_data[i].input_length > width)
  1025.        dialog_data[i].input_length = width;
  1026.     buffer[i] = malloc (1024);
  1027.     inputs[i] = malloc (1024);
  1028.     dialog_data[i].initializer (buffer[i], inputs[i],
  1029.                                 dialog_data[i].return_addr);
  1030.   }
  1031.   x_button = (cols / 2) - max_button_len * buttons / 2;
  1032.   if (*ret >= items + buttons || *ret < 0)
  1033.     *ret = 0;
  1034.   pos = *ret;
  1035.   while ((pos < items) && !(dialog_data[pos].editable))
  1036.   { pos++;
  1037.     if (pos >= items + buttons)
  1038.       pos = 0;
  1039.   }
  1040.   y1 = (rows / 2) - (items + 1) / 2 - 3;
  1041.   y2 = rows - y1 - 1;
  1042.   save = debug_screen_save;
  1043.   debug_screen_save = get_screen ();                                            
  1044.   screen_attr = screen_attr_ffocus;
  1045.   double_frame (x1, y1, x2, y2, tittle);
  1046.   screen_attr = screen_attr_normal;
  1047.   for (i = y1 + 1; i < y2; i++)
  1048.     putl(x1 + 1, i, x2 - x1 - 2, " ");
  1049.   for (i = 0; i < items; i++)
  1050.     putl (x1 + 2, y1 + i + 2, max_field_len, dialog_data[i].field_name);
  1051.   put_screen (debug_screen_save);
  1052.   do
  1053.   { for (i = 0; i < items; i++)
  1054.     { screen_attr = (i == pos) ? screen_attr_dfocus : screen_attr_normal;
  1055.       putl (x1 + max_field_len + 3, y1 + i + 2, dialog_data[i].input_length,
  1056.             buffer[i]);
  1057.     }                                                 
  1058.     for (i = 0; i < buttons; i++)
  1059.     { screen_attr = (i + items == pos) ? screen_attr_dfocus 
  1060.                                        : screen_attr_button;
  1061.       putl (x_button + i * max_button_len , y1 + items + 3, 
  1062.             max_button_len - 2, button_data[i].name);
  1063.     }                                                 
  1064.     put_screen (debug_screen_save);
  1065.     if (pos < items)
  1066.     { if (!dialog_data[pos].editor (inputs[pos],
  1067.                                     dialog_data[pos].return_addr,
  1068.                                     x1 + max_field_len + 3,
  1069.                                     y1 + pos + 2,
  1070.                                     dialog_data[pos].input_length, &key))
  1071.       { dialog_data[pos].formatter (buffer[pos], read_buffer);
  1072.         strcpy (inputs[pos], read_buffer);
  1073.         dialog_data[pos].evaluater ((void *)dialog_data[pos].return_addr, 
  1074.                                     read_buffer);
  1075.         if (!key)
  1076.           key = K_Down;
  1077.       } else
  1078.         dialog_data[pos].initializer (buffer[pos], inputs[pos],
  1079.                                       dialog_data[pos].return_addr);
  1080.       screen_attr = screen_attr_dfocus;
  1081.       putl (x1 + max_field_len + 3, y1 + pos + 2,
  1082.             dialog_data[pos].input_length, buffer[pos]);
  1083.       put_screen (debug_screen_save);
  1084.     }
  1085.     if (key == 0)
  1086.       key = getykey();
  1087.     switch(key)     
  1088.     { case K_Up:
  1089.       case K_EUp:
  1090.       case K_BackTab:
  1091.       case K_Control_P:
  1092.         do
  1093.         { if (!pos)
  1094.             pos = items + buttons - 1;
  1095.           else
  1096.             pos--;
  1097.         } while ((pos < items) && !(dialog_data[pos].editable));
  1098.         key = 0;
  1099.         break;
  1100.       case K_Down:
  1101.       case K_EDown:
  1102.       case K_Tab:      
  1103.       case K_Control_N:
  1104.         do
  1105.         { pos++;
  1106.           if (pos >= items + buttons)
  1107.             pos = 0;
  1108.         } while ((pos < items) && !(dialog_data[pos].editable));
  1109.         key = 0;
  1110.         break;
  1111.       case K_Return:
  1112.         if (pos >= items)
  1113.         { button_data[pos - items].action (dialog_data); 
  1114.           if (button_data[pos - items].stay)
  1115.             for (i = 0; i < items; i++)
  1116.               dialog_data[i].initializer (buffer[i], inputs[i],
  1117.                                           dialog_data[i].return_addr); 
  1118.           else
  1119.           { *ret = pos - items + 1;
  1120.             leave = 1;
  1121.           }
  1122.           key = 0;
  1123.           screen_attr = screen_attr_ffocus;
  1124.           double_frame (x1, y1, x2, y2, tittle);
  1125.           screen_attr = screen_attr_normal;
  1126.           for (i = y1 + 1; i < y2; i++)
  1127.             putl(x1 + 1, i, x2 - x1 - 2, " ");
  1128.           for (i = 0; i < items; i++)
  1129.             putl (x1 + 2, y1 + i + 2, max_field_len, dialog_data[i].field_name);
  1130.         }  
  1131.         break;
  1132.       case K_Escape:
  1133.         key = getykey ();
  1134.         if (key != K_Escape)
  1135.           break;                                   /* Else fall through */
  1136.       case K_Control_G:
  1137.         leave = 1;
  1138.         *ret = 0;
  1139.         break;
  1140.       default:
  1141.         if (pos >= items)
  1142.           key = 0;
  1143.         break;
  1144.     }
  1145.   } while (!leave);                                      
  1146.   for (i = 0; i < items; i++)
  1147.   { free (buffer[i]);
  1148.     free (inputs[i]);
  1149.   }
  1150.   free (buffer);
  1151.   free (inputs);
  1152.   free (debug_screen_save);
  1153.   debug_screen_save = save;
  1154. }
  1155. /* ---------------------------------------------------------------------- */
  1156. char *
  1157. open_win(int width, int height, int attribute, int border,
  1158.      int *x_start, int *y_start, int *actual_width, char *tittle)
  1159. {
  1160.   char *saved;
  1161.   int x1, y1, x2, y2;
  1162.  
  1163.   saved = debug_screen_save;
  1164.   debug_screen_save = get_screen();
  1165.   x1 = cols / 2 - width / 2;
  1166.   if (x1 < 1)
  1167.     x1 = 1;
  1168.   x2 = x1 + width;
  1169.   if (x2 > cols - 1)
  1170.     x2 = cols - 1;
  1171.   y1 = rows / 2 - height / 2;
  1172.   if (y1 < 1)
  1173.     y1 = 1;
  1174.   y2 = y1 + height;
  1175.   if (y2 > rows - 1)
  1176.     y2 = rows - 1;
  1177.   screen_attr = attribute;
  1178.   switch (border)
  1179.   {
  1180.     case 0:
  1181.     case 1:
  1182.       frame (x1 - 1, y1 - 1, x2, y2, tittle);
  1183.       break;
  1184.     case 2:
  1185.       double_frame (x1 - 1, y1 - 1, x2, y2, tittle);
  1186.   }
  1187.   screen_attr = screen_attr_normal;
  1188.   *x_start = x1;
  1189.   *y_start = y1;
  1190.   *actual_width = x2 - x1;
  1191.   for (x2 = y1; x2 < y2; x2++)
  1192.     putl (x1, x2, *actual_width, " ");
  1193.   refresh ();
  1194.  
  1195.   return saved;
  1196. }
  1197. /* ---------------------------------------------------------------------- */
  1198. void
  1199. close_win(char *saved)
  1200. {
  1201.   free (debug_screen_save);
  1202.   debug_screen_save = saved;
  1203.   refresh ();
  1204. }
  1205. /* ---------------------------------------------------------------------- */
  1206. void
  1207. init_text (WIN_TEXT *text, char *tittle)
  1208. {
  1209.   text->page = 0;
  1210.   text->lines = 0; 
  1211.   if (tittle)
  1212.     text->tittle = strdup (tittle);
  1213.   else
  1214.     text->tittle = 0;
  1215. }
  1216. /* ---------------------------------------------------------------------- */
  1217. void
  1218. add_text (WIN_TEXT *text, char *line)
  1219. {
  1220.   char *p;
  1221.  
  1222.   if (!line[0])
  1223.     return;
  1224.  
  1225.   p = strdup (line);
  1226.   if (p)
  1227.   { text->lines++;
  1228.     if (text->lines == 1)
  1229.       text->page = malloc (sizeof (char *));
  1230.     else
  1231.       text->page = realloc (text->page, text->lines * sizeof (char *));
  1232.     text->page[text->lines - 1] = p;
  1233.   }
  1234. }
  1235. /* ---------------------------------------------------------------------- */
  1236. void
  1237. free_text (WIN_TEXT *text)
  1238. {
  1239.   int i;
  1240.  
  1241.   for (i = 0; i < text->lines; i++)
  1242.     free (text->page[i]);
  1243.  
  1244.   free (text->page);             
  1245.   free (text->tittle);
  1246.   text->lines = 0;
  1247.   text->page = 0;     
  1248.   text->tittle = 0;
  1249. }
  1250. /* ---------------------------------------------------------------------- */
  1251. void
  1252. text_win (WIN_TEXT text, int user_width, int user_height)
  1253. {
  1254.   int x, y, i, width, height, not_done = 1, key, len;
  1255.   int start_line = 0, pos = 0, textoffset = 0;
  1256.   char *window_save;
  1257.  
  1258.   if (user_height > rows - 1)
  1259.     height = rows - 1;
  1260.   else
  1261.     height = user_height;
  1262.   window_save = open_win (user_width, height, screen_attr_ffocus,
  1263.               single_border, &x, &y, &width, text.tittle);
  1264.   height -= 1;
  1265.   while (not_done)
  1266.   {
  1267.     screen_attr = screen_attr_normal;
  1268.     for (i = 0; i <= height; i++)
  1269.     {
  1270.       if (i + start_line < text.lines)              
  1271.       { len = strlen (text.page[i + start_line]);
  1272.     putl (x, y + i, width, text.page[i + start_line] + 
  1273.               ((textoffset < len) ? textoffset : len));
  1274.       } else
  1275.     putl (x, y + i, width , " ");
  1276.     }
  1277.     screen_attr = screen_attr_focus;
  1278.     len = strlen (text.page[pos + start_line]);
  1279.     putl (x, y + pos, width, text.page[pos + start_line] + 
  1280.           ((textoffset < len) ? textoffset : len));
  1281.     refresh ();
  1282.     key = getykey ();
  1283.     if (key == K_Escape)
  1284.     { switch (key = getykey ())
  1285.       { case 'v':
  1286.         case 'V':
  1287.           key = K_PageUp;
  1288.           break;
  1289.         case '<':
  1290.           key = K_Home;
  1291.           break;
  1292.         case '>':
  1293.           key = K_End;
  1294.           break;
  1295.         case K_Escape:
  1296.           key = K_Control_G;
  1297.           break;
  1298.         default:
  1299.           key = 0;
  1300.           break;
  1301.       }
  1302.     }           
  1303.     if (key == K_Control_X)
  1304.     { switch (key = getykey ())
  1305.       { case K_Control_W:
  1306.           write_log (x, y, x + width, y + height);
  1307.           break;
  1308.         case '<':
  1309.           textoffset++;
  1310.           break;
  1311.         case '>':
  1312.           if (textoffset)
  1313.             textoffset--;
  1314.           break;
  1315.       } 
  1316.       key = 0;
  1317.     }
  1318.     switch (key)
  1319.     {
  1320.       case K_Up:
  1321.       case K_EUp:
  1322.       case K_Left:
  1323.       case K_ELeft:
  1324.       case K_Control_P:
  1325.       case K_Control_B:
  1326.     if (pos == 0)
  1327.     { if (start_line)
  1328.         start_line--;
  1329.     }
  1330.     else
  1331.       pos--;
  1332.     break;
  1333.       case K_Down:
  1334.       case K_EDown:    
  1335.       case K_Right:
  1336.       case K_ERight:
  1337.       case K_Control_N:
  1338.       case K_Control_F:
  1339.     if (pos < height)
  1340.     { if (start_line + pos < text.lines - 1)
  1341.         pos++;
  1342.     } else
  1343.     { if (start_line + pos < text.lines - 1)
  1344.        start_line++;
  1345.     }
  1346.     break;
  1347.       case K_PageUp:
  1348.       case K_EPageUp:  
  1349.         if (start_line > height - 1)
  1350.           start_line -= height - 1;
  1351.         else
  1352.           start_line = 0;
  1353.         break;
  1354.       case K_PageDown:
  1355.       case K_EPageDown:
  1356.       case K_Control_V:            
  1357.         if (start_line < text.lines - height - 1)
  1358.           start_line += height - 1;      
  1359.         if (pos + start_line >= text.lines - 1)
  1360.           pos = text.lines - start_line - 1;
  1361.         break;
  1362.       case K_Home: 
  1363.       case K_EHome:
  1364.         start_line = 0;
  1365.         pos = 0;
  1366.         break;
  1367.       case K_End:  
  1368.       case K_EEnd:
  1369.         if (start_line + height < text.lines - 1)
  1370.         { start_line = text.lines - height - 1;
  1371.           pos = text.lines - start_line - 1;
  1372.         }
  1373.         break;
  1374.       case K_Return:
  1375.       case K_Control_G:
  1376.     not_done = 0;
  1377.     }
  1378.   }
  1379.   close_win (window_save);
  1380. }
  1381. /* ---------------------------------------------------------------------- */
  1382. static void
  1383. seperate_hotkey (const char *s, char *s1, char *s2, char *s3)
  1384. { int first, second, len;
  1385.   len = strlen (s);
  1386.   s1[0] = 0;
  1387.   s2[0] = 0;
  1388.   s3[0] = 0;
  1389.   for (first = 0; (first < len) && (s[first] != '~'); first++)
  1390.     ;
  1391.   if (s[first] != '~')
  1392.   { sprintf (s1, s);
  1393.     return;
  1394.   }
  1395.   strncpy (s1, s, first);
  1396.   s1[first] = 0;
  1397.   for (second = first + 1; (second < len) && (s[second] != '~'); second++)
  1398.     ;
  1399.   if (s[second] != '~')
  1400.   { sprintf (s2, s + first + 1);
  1401.     return;
  1402.   }
  1403.   strncpy (s2, s + first + 1, second - first - 1);
  1404.   s2[second - first - 1] = 0;
  1405.   strcpy (s3, s + second + 1);
  1406. }
  1407. /* ---------------------------------------------------------------------- */
  1408. int
  1409. display_bar_menu (MENU_ITEM menu_data[], int *pos)
  1410. { char *begin = alloca (cols), *mid = alloca (cols), *end = alloca (cols);
  1411.   int i, len, l_begin, l_mid, l_end, x = 0;
  1412.  
  1413.   for (i = 1; menu_data[i].name && x < cols; i++)
  1414.   { seperate_hotkey (menu_data[i].name, begin, mid, end);
  1415.     l_begin = strlen (begin);
  1416.     l_mid   = strlen (mid);
  1417.     l_end   = strlen (end);
  1418.     len = l_begin + l_mid + l_end + 2;
  1419.     if (i == menu_data[0].type)
  1420.     {
  1421.       screen_attr = screen_attr_error;
  1422.       putl (x, 0, 1, "*");
  1423.       if (l_begin)
  1424.         putl (x + 1, 0, l_begin, begin);
  1425.       if (l_mid)
  1426.         putl (x + 1 + l_begin, 0, l_mid, mid);
  1427.       if (l_end)
  1428.         putl (x + 1 + l_begin + l_mid, 0, l_end, end);
  1429.       *pos = x;
  1430.     }
  1431.     else
  1432.     { screen_attr = screen_attr_normal;
  1433.       putl (x, 0, 1, " ");
  1434.       if (l_begin)
  1435.         putl (x + 1, 0, l_begin, begin);
  1436.       if (l_mid)
  1437.       { screen_attr = screen_attr_hot;
  1438.         putl (x + 1 + l_begin, 0, l_mid, mid);
  1439.         screen_attr = screen_attr_normal;
  1440.       }
  1441.       if (l_end)
  1442.         putl (x + 1 + l_begin + l_mid, 0, l_end, end);
  1443.     } 
  1444.     x += len + 1;                       
  1445.     screen_attr = screen_attr_normal;
  1446.     putl (x - 3, 0, 3, " ");
  1447.   }
  1448.   i--;
  1449.   if (x < cols - 1)
  1450.     putl (x, 0, cols - x, " ");
  1451.   refresh ();
  1452.   return i;
  1453. }
  1454. /* ---------------------------------------------------------------------- */
  1455. int
  1456. display_pop_menu (MENU_ITEM menu_data[], char *tittle, int x_pos, int y_pos)
  1457. { char *begin = alloca (cols), *mid = alloca (cols), *end = alloca (cols);
  1458.   int i, len, l_begin, l_mid, l_end;
  1459.   int y = y_pos + 1, maxlen = 0;
  1460.  
  1461.   for (i = 1; menu_data[i].name; i++)
  1462.   {
  1463.     len = strlen (menu_data[i].name) + 2;
  1464.     if (len > maxlen)
  1465.       maxlen = len;
  1466.   }              
  1467.   maxlen -= 2;
  1468.   for (i = 1; menu_data[i].name; i++)
  1469.   { seperate_hotkey (menu_data[i].name, begin, mid, end);
  1470.     l_begin = strlen (begin);
  1471.     l_mid   = strlen (mid);
  1472.     l_end   = strlen (end);
  1473.     len = l_begin + l_mid + l_end;
  1474.     
  1475.     if (i == menu_data[0].type)
  1476.     { screen_attr = screen_attr_error;
  1477.       putl (x_pos + 1, y, 1 , "*");
  1478.       if (l_begin)
  1479.         putl (x_pos + 2, y, l_begin, begin);
  1480.       if (l_mid)
  1481.         putl (x_pos + 2 + l_begin, y, l_mid, mid);
  1482.       if (l_end)
  1483.         putl (x_pos + 2 + l_begin + l_mid, y, l_end, end);
  1484.       putl (x_pos + 2 + l_begin + l_mid + l_end, y, maxlen - len, " ");
  1485.     } else
  1486.     { screen_attr = screen_attr_normal;
  1487.       putl (x_pos + 1, y, 1 , " ");
  1488.       if (l_begin)
  1489.         putl (x_pos + 2, y, l_begin, begin);
  1490.       if (l_mid)  
  1491.       { screen_attr = screen_attr_hot;
  1492.         putl (x_pos + 2 + l_begin, y, l_mid, mid);
  1493.         screen_attr = screen_attr_normal;
  1494.       }
  1495.       if (l_end)
  1496.         putl (x_pos + 2 + l_begin + l_mid, y, l_end, end);
  1497.       putl (x_pos + 2 + l_begin + l_mid + l_end, y, maxlen - len, " ");
  1498.     }
  1499.     y++;
  1500.   }
  1501.   i--;
  1502.   screen_attr = screen_attr_focus;
  1503.   frame (x_pos, y_pos, x_pos + maxlen + 1, y, tittle);
  1504.   screen_attr = screen_attr_normal;
  1505.   refresh ();
  1506.   return i;
  1507. }
  1508. /* ---------------------------------------------------------------------- */
  1509. static int
  1510. search_hotkey (MENU_ITEM menu_data[])
  1511. { int i, len, maxlen = 0;
  1512.  
  1513.   for (i = 1; menu_data[i].name; i++)
  1514.   { len = strlen (menu_data[i].hot_key);
  1515.     if (len > maxlen)
  1516.       maxlen = len;
  1517.   }                                  
  1518.   len = strlen (read_buffer);
  1519.   while (maxlen < len)
  1520.   { for (i = 0; i < len; i++)
  1521.       read_buffer[i] = read_buffer[i + 1];
  1522.     len--;
  1523.   }
  1524.   for (i = 1; menu_data[i].name; i++)
  1525.   { if (strcmp (read_buffer, menu_data[i].hot_key) == 0)
  1526.       return (i);
  1527.   }
  1528.   return (0);
  1529. }
  1530. /* ---------------------------------------------------------------------- */
  1531. void
  1532. menu (MENU_ITEM menu_data[], int *BarSelect, int *PopSelect)
  1533. { int buf_pos = 0;
  1534.   int bar_item_num, pop_item_num;
  1535.   int not_done, x, key = 0, lastkey = 0, downonce = 0;
  1536.   char *save;
  1537.  
  1538.   save = get_old_screen ();
  1539.   read_buffer[buf_pos] = 0;
  1540. back_to_menu_bar:
  1541.   not_done = 1;
  1542.   bar_item_num = display_bar_menu (menu_data, &x);
  1543.   while (not_done)
  1544.   { if (lastkey)   
  1545.       key = K_Return;
  1546.     else if (key)
  1547.       lastkey = 1;
  1548.     else
  1549.       key = getykey ();
  1550.     switch (key)
  1551.     { case K_Left:
  1552.       case K_ELeft: 
  1553.       case K_BackTab:
  1554.       case K_Control_B:
  1555.         buf_pos = 0;
  1556.     menu_data[0].type--;
  1557.     if (menu_data[0].type < 1)
  1558.       menu_data[0].type = bar_item_num;          
  1559.         if (downonce)
  1560.         { lastkey = 1;
  1561.           not_done = 0;
  1562.         }
  1563.     break;
  1564.       case K_Right:
  1565.       case K_ERight:   
  1566.       case K_Tab:
  1567.       case K_Control_F:
  1568.         buf_pos = 0;
  1569.     menu_data[0].type++;
  1570.     if (menu_data[0].type > bar_item_num)
  1571.       menu_data[0].type = 1;
  1572.         if (downonce)
  1573.         { lastkey = 1;
  1574.           not_done = 0;
  1575.         }
  1576.     break;
  1577.       case K_Down:
  1578.       case K_EDown:    
  1579.       case K_Control_N:
  1580.       case K_Control_P:
  1581.       case K_Return:
  1582.     not_done = 0;
  1583.     break;       
  1584.       case K_Escape:
  1585.         key = getykey ();
  1586.         if (key != K_Escape)
  1587.         { read_buffer[buf_pos++] = K_Escape;
  1588.           read_buffer[buf_pos++] = key;
  1589.           read_buffer[buf_pos] = 0;
  1590.           bar_item_num = search_hotkey (menu_data);
  1591.           buf_pos = strlen (read_buffer);
  1592.           if (bar_item_num)
  1593.           { menu_data[0].type = bar_item_num;
  1594.             not_done = 0;
  1595.           }
  1596.           break;
  1597.         }                                             /* Else falls through */
  1598.       case K_Control_G:
  1599.     restore_screen (save);
  1600.     refresh ();
  1601.         *BarSelect = 0;
  1602.         *PopSelect = 0;
  1603.         return;  
  1604.       default:     
  1605.         read_buffer[buf_pos++] = key;          
  1606.         read_buffer[buf_pos] = 0;
  1607.         bar_item_num = search_hotkey (menu_data);
  1608.         buf_pos = strlen (read_buffer);
  1609.         if (bar_item_num)
  1610.         { menu_data[0].type = bar_item_num;
  1611.           not_done = 0;
  1612.         }
  1613.         break;
  1614.     }
  1615.     key = 0;
  1616.     bar_item_num = display_bar_menu (menu_data, &x);
  1617.   }                                    
  1618.   *BarSelect = menu_data[0].type; 
  1619.   if (menu_data[*BarSelect].type == ITEM_TYPE)
  1620.   { if (lastkey)                                         
  1621.     { lastkey = 0;
  1622.       goto back_to_menu_bar;
  1623.     }
  1624.     restore_screen (save);
  1625.     refresh ();
  1626.     return;
  1627.   }                         
  1628.   lastkey = 0;
  1629.   downonce = 1;
  1630.   not_done = 1;
  1631.   buf_pos = 0;
  1632.   while (not_done)
  1633.   { pop_item_num = display_pop_menu (menu_data[*BarSelect].child, 0, x, 1);
  1634.     switch (key = getykey ())
  1635.     {
  1636.       case K_Up:
  1637.       case K_EUp:
  1638.       case K_Control_P:
  1639.         buf_pos = 0;
  1640.     menu_data[*BarSelect].child[0].type--;
  1641.     if (menu_data[*BarSelect].child[0].type < 1)
  1642.       menu_data[*BarSelect].child[0].type = pop_item_num;
  1643.     break;
  1644.       case K_Down:
  1645.       case K_EDown:    
  1646.       case K_Control_N:
  1647.         buf_pos = 0;
  1648.     menu_data[*BarSelect].child[0].type++;
  1649.     if (menu_data[*BarSelect].child[0].type > pop_item_num)
  1650.       menu_data[*BarSelect].child[0].type = 1;
  1651.     break;
  1652.       case K_Return:
  1653.     not_done = 0;
  1654.     break;
  1655.       case K_Escape:
  1656.         key = getykey ();
  1657.         if (key != K_Escape)
  1658.         { read_buffer[buf_pos++] = K_Escape;
  1659.           read_buffer[buf_pos++] = key;
  1660.           read_buffer[buf_pos] = 0;
  1661.           pop_item_num = search_hotkey (menu_data[*BarSelect].child);
  1662.           buf_pos = strlen (read_buffer);
  1663.           if (pop_item_num)
  1664.           { menu_data[*BarSelect].child[0].type = pop_item_num;
  1665.             not_done = 0;
  1666.           }
  1667.           break;
  1668.         }                                             /* Else falls through */
  1669.       case K_Control_G:
  1670.     restore_screen (save);
  1671.     refresh ();
  1672.     save = get_old_screen ();
  1673.         key = 0;                                                     
  1674.         downonce = 0;
  1675.     goto back_to_menu_bar;
  1676.       case K_Left:
  1677.       case K_ELeft:
  1678.       case K_Right:
  1679.       case K_ERight:   
  1680.       case K_Tab:
  1681.       case K_BackTab:
  1682.       case K_Control_F:
  1683.       case K_Control_B:
  1684.     restore_screen (save);
  1685.     refresh ();
  1686.     save = get_old_screen ();
  1687.     goto back_to_menu_bar;
  1688.       default:                                                   
  1689.         read_buffer[buf_pos++] = key;          
  1690.         read_buffer[buf_pos] = 0;
  1691.         pop_item_num = search_hotkey (menu_data[*BarSelect].child);
  1692.         buf_pos = strlen (read_buffer);
  1693.         if (pop_item_num)
  1694.         { menu_data[*BarSelect].child[0].type = pop_item_num;
  1695.           not_done = 0;
  1696.         }
  1697.         break;
  1698.     }
  1699.   }
  1700.   *PopSelect = menu_data[*BarSelect].child[0].type;
  1701.   restore_screen (save);
  1702.   refresh ();
  1703. }
  1704. /* ---------------------------------------------------------------------- */
  1705. void
  1706. pop_menu (MENU_ITEM menu_data[], char *tittle, int x, int y, int *PopSelect)
  1707. { int buf_pos = 0;
  1708.   int pop_item_num;
  1709.   int not_done;
  1710.   char *save;
  1711.   int key;
  1712.  
  1713.   save = get_old_screen ();
  1714.   read_buffer[buf_pos] = 0;
  1715.   not_done = 1;
  1716.   while (not_done)
  1717.   { pop_item_num = display_pop_menu (menu_data, tittle, x, y);
  1718.     key = getykey ();
  1719.     switch (key)
  1720.     { case K_Up:
  1721.       case K_EUp:
  1722.       case K_Control_P:
  1723.         buf_pos = 0;
  1724.     menu_data[0].type--;
  1725.     if (menu_data[0].type < 1)
  1726.       menu_data[0].type = pop_item_num;
  1727.     break;
  1728.       case K_Down:
  1729.       case K_EDown:
  1730.       case K_Control_N:
  1731.         buf_pos = 0;
  1732.     menu_data[0].type++;
  1733.     if (menu_data[0].type > pop_item_num)
  1734.       menu_data[0].type = 1;
  1735.     break;
  1736.       case K_Return:
  1737.     not_done = 0;
  1738.     break; 
  1739.       case K_Escape:
  1740.         key = getykey ();
  1741.         if (key != K_Escape)
  1742.         { read_buffer[buf_pos++] = K_Escape;
  1743.           read_buffer[buf_pos++] = key;
  1744.           read_buffer[buf_pos] = 0;
  1745.           pop_item_num = search_hotkey (menu_data);
  1746.           buf_pos = strlen (read_buffer);
  1747.           if (pop_item_num)
  1748.           { menu_data[0].type = pop_item_num;
  1749.             not_done = 0;
  1750.           }
  1751.           break;
  1752.         }                                             /* Else falls through */
  1753.       case K_Control_G:
  1754.         restore_screen (save);
  1755.         refresh ();
  1756.         *PopSelect = 0;
  1757.         return;
  1758.       default: 
  1759.         read_buffer[buf_pos++] = key;          
  1760.         read_buffer[buf_pos] = 0;
  1761.         pop_item_num = search_hotkey (menu_data);
  1762.         buf_pos = strlen (read_buffer);
  1763.         if (pop_item_num)
  1764.         { menu_data[0].type = pop_item_num;
  1765.           not_done = 0;
  1766.         }
  1767.         break;
  1768.     }
  1769.   }
  1770.   *PopSelect = menu_data[0].type;
  1771.   restore_screen (save);
  1772.   refresh ();
  1773. }
  1774. /* ---------------------------------------------------------------------- */
  1775. void
  1776. show_menu_bar (MENU_ITEM menu_data[])
  1777. { int old_menu_pos, temp_bar_sel;
  1778.  
  1779.   old_menu_pos = menu_data[0].type;
  1780.   menu_data[0].type = 0;
  1781.   display_bar_menu (menu_data, &temp_bar_sel);
  1782.   menu_data[0].type = old_menu_pos;
  1783. }
  1784. /* ---------------------------------------------------------------------- */
  1785. void
  1786. parse_string (PARSE_DEF definition[], char *s)
  1787. { int i;
  1788.   char sw[64], val[100];
  1789.  
  1790.   while (1)
  1791.   { if (sscanf (s, "%s%n", sw, &i) < 1)
  1792.       break;
  1793.     s += i;
  1794.     if (sscanf (s, "%s%n", val, &i) < 1)
  1795.       break;
  1796.     s += i;
  1797.     for (i = 0; definition[i].sw; i++)
  1798.       if (stricmp (sw, definition[i].sw) == 0)
  1799.       { if (definition[i].type == STR_TYPE)
  1800.           strcpy (definition[i].val.s_val, val);
  1801.         else
  1802.           *(definition[i].val.i_val) = atol (val);
  1803.       }
  1804.   }
  1805. }
  1806. /* ---------------------------------------------------------------------- */
  1807. void
  1808. re_start_transfer ()
  1809. { first_transfer = 1;
  1810. }
  1811. /* ---------------------------------------------------------------------- */
  1812. static char *filename = 0;
  1813. /* ---------------------------------------------------------------------- */
  1814. void
  1815. write_log (int x1, int y1, int x2, int y2)
  1816. { unsigned char *p;
  1817.   int r, c;
  1818.   FILE *f;
  1819.   struct stat statbuf;
  1820.  
  1821.   p = (unsigned char *)(debug_screen_save + 3);
  1822.   if (!filename)
  1823.     if (my_read_string("Enter filename: "))
  1824.        return;
  1825.     else
  1826.       filename = strdup(read_buffer);
  1827.  
  1828.   if (stat(filename,&statbuf) != -1)
  1829.     f = fopen(filename,"a+");
  1830.   else
  1831.     f = fopen(filename,"w+");
  1832.   if (f)
  1833.   { char temp_ch;
  1834.     struct date curr_date;
  1835.     struct time curr_time;
  1836.  
  1837.     getdate (&curr_date);
  1838.     gettime (&curr_time);
  1839.     for (r = 0; r < 20; r++)
  1840.       fputc ('=', f);
  1841.     sprintf (read_buffer, "%02d:%02d:%02d %02d/%02d/%04d ====\n",
  1842.              curr_time.ti_hour, curr_time.ti_min, curr_time.ti_sec,
  1843.              curr_date.da_mon,  curr_date.da_day, curr_date.da_year);
  1844.     fputs (read_buffer, f);
  1845.  
  1846.     for (r = y1; r < y2; r++)
  1847.     { for (c = x1; c < x2; c++)
  1848.       { temp_ch = p[(r * cols + c) * 2];
  1849.         switch (temp_ch)
  1850.         { case 10:
  1851.           case 13:
  1852.           case 26:
  1853.             temp_ch = '.';
  1854.     }
  1855.     putc (temp_ch, f);
  1856.       }
  1857.       fputc ('\n', f);
  1858.     }
  1859.     fclose(f);
  1860.   } else
  1861.   { message(CL_Error,"Cannot write to file %s",filename);
  1862.     free (filename);
  1863.     filename = 0;
  1864.   }
  1865. }
  1866. /* ---------------------------------------------------------------------- */
  1867. static void               /* Will use as much memory as needed, not nice. */
  1868. old_read_log (void)
  1869. { FILE *f; 
  1870.   char *p;
  1871.   int len;
  1872.   WIN_TEXT read_text;
  1873.  
  1874.   if (!filename)
  1875.     if (my_read_string("Enter filename: "))
  1876.       return;
  1877.     else
  1878.       filename = strdup(read_buffer);
  1879.   f = fopen(filename,"r+");
  1880.   if (f)      /* File exist */
  1881.   { init_text (&read_text, filename);
  1882.     p = malloc (max_cols + 5);
  1883.     do
  1884.     { fgets (p, max_cols + 2, f);
  1885.       len = strlen (p);
  1886.       if (len)
  1887.       { if (p[len - 1] == 13 || p[len - 1] == 10)
  1888.           p[len - 1] = 0;
  1889.       }
  1890.       len = feof (f);
  1891.       if (!len)
  1892.         add_text (&read_text, p);
  1893.     } while (!len);
  1894.     fclose (f);
  1895.     free (p);
  1896.     text_win (read_text, cols - 2, rows - 2);
  1897.     free_text (&read_text);
  1898.   } else
  1899.   { message(CL_Error,"Cannot open file %s",filename);
  1900.     free (filename);
  1901.     filename = 0;
  1902.   }
  1903. }
  1904. /* ---------------------------------------------------------------------- */
  1905. #define TEXT_LEN 128
  1906. #define STRI_LEN 120
  1907. /* ---------------------------------------------------------------------- */
  1908. static FILE *
  1909. init_win_file (WIN_TEXT *text, char *fname, int lines, int *f_pos)
  1910. { FILE *f;
  1911.   int i, pos, fpos, not_eof, read_bytes, left;
  1912.   char *p, *temp = alloca (TEXT_LEN);
  1913.   
  1914.   f = fopen (fname, "rb");
  1915.   if (!f)
  1916.     return (f);
  1917.   *f_pos = 0;
  1918.   i = 0;
  1919.   pos = 0;
  1920.   fpos = 0;
  1921.   do
  1922.   { fseek (f, fpos, SEEK_SET);
  1923.     read_bytes = fread (read_buffer, 1, 4096, f);
  1924.     not_eof = (read_bytes == 4096) ? 1 : 0;
  1925.     p = read_buffer;
  1926.     left = read_bytes;
  1927.     while (1)
  1928.     { for (pos = 0; pos < left && p[pos] != 0x0a; pos++)
  1929.         ;
  1930.       if (pos == left)
  1931.         break;
  1932.       p[pos] = 0;
  1933.       if (pos > 0 && p[pos - 1] == 0x0d)
  1934.         p[pos - 1] = 0;
  1935.       strcpy (temp, p);
  1936.       p += pos + 1;
  1937.       left -= pos + 1;
  1938.       pos--;
  1939.       for (; pos < TEXT_LEN; pos++)
  1940.         temp[pos] = ' ';
  1941.       temp[pos - 1] = 0;
  1942.       add_text (text, temp);
  1943.       i++;
  1944.       if (i == lines)
  1945.         break;
  1946.     }
  1947.     fpos += read_bytes - left;
  1948.   } while (not_eof && i < lines);
  1949.   return (f);
  1950. }
  1951. /* ---------------------------------------------------------------------- */
  1952. static int
  1953. read_win_file (WIN_TEXT *text, FILE *f, int d_lines, int *f_pos)
  1954. { int pos, fpos, bytes_to_read, bytes_read, lines, i, left;
  1955.   char *p;
  1956.   
  1957.   if (d_lines < 0)
  1958.   { if (*f_pos == 0)
  1959.       return (0);
  1960.     lines = 0;
  1961.     d_lines *= -1;
  1962.     do
  1963.     { fpos = *f_pos - 4096;
  1964.       if (fpos < 0)
  1965.         fpos = 0;
  1966.       bytes_to_read = *f_pos - fpos;
  1967.       fseek (f, fpos, SEEK_SET);
  1968.       bytes_read = fread (read_buffer, 1, bytes_to_read, f);
  1969.       if (bytes_read != bytes_to_read)
  1970.       { message (CL_Error, "Error reading file.");
  1971.         return (0);
  1972.       }
  1973.       for (pos = bytes_read - 1; pos > 0 && lines < d_lines; pos--)
  1974.         if (read_buffer[pos] == 0x0a)
  1975.         { lines++;
  1976.           *f_pos = fpos + pos - 1;
  1977.           if (*f_pos < 0)
  1978.             *f_pos = 0;
  1979.         }
  1980.       if (fpos == 0 && lines < d_lines)
  1981.       { lines++;
  1982.         *f_pos = 0;
  1983.       }
  1984.     } while (lines < d_lines && fpos > 0);
  1985.     for (pos = text->lines - 1; pos >= lines; pos--)
  1986.       strcpy (text->page[pos], text->page[pos - lines]);
  1987.     fpos = *f_pos;
  1988.     pos = 0;
  1989.     do
  1990.     { fseek (f, fpos, SEEK_SET);
  1991.       bytes_read = fread (read_buffer, 1, 4096, f);
  1992.       p = read_buffer;
  1993.       left = bytes_read;
  1994.       while (1)
  1995.       { for (i = 0; i < left && p[i] != 0x0a; i++)
  1996.           ;
  1997.         if (i == left)
  1998.           break;
  1999.         p[i] = 0;
  2000.         if (i > 0 && p[i - 1] == 0x0d)
  2001.           p[i - 1] = 0;
  2002.         strncpy (text->page[pos], p, STRI_LEN);
  2003.         p += i + 1;
  2004.         left -= i + 1;
  2005.         pos++;
  2006.         if (pos == lines)
  2007.           break;
  2008.       }
  2009.       fpos += bytes_read - left;
  2010.     } while (pos < lines && bytes_read == 4096);
  2011.     return (lines);
  2012.   }
  2013.   else
  2014.   { int start_f_pos;
  2015.  
  2016.     lines = 0;
  2017.     fpos = *f_pos;
  2018.     left = text->lines;
  2019.     bytes_read = 4096;
  2020.     while (lines < text->lines && bytes_read == 4096)
  2021.     { fseek (f, fpos, SEEK_SET);
  2022.       bytes_read = fread (read_buffer, 1, 4096, f);
  2023.       i = fpos;
  2024.       for (pos = 0; pos < bytes_read && lines < text->lines; pos++)
  2025.         if (read_buffer[pos] == 0x0a)
  2026.         { lines++;
  2027.           if (left > 0)
  2028.           { left--;
  2029.             *f_pos = i + pos + 1;
  2030.           }
  2031.           fpos = i + pos + 1;
  2032.         }
  2033.     }
  2034.     start_f_pos = fpos;
  2035.     bytes_read = 4096;
  2036.     lines = 0;
  2037.     while (lines < d_lines && bytes_read == 4096)
  2038.     { fseek (f, fpos, SEEK_SET);
  2039.       bytes_read = fread (read_buffer, 1, 4096, f);
  2040.       p = read_buffer;
  2041.       i = fpos;
  2042.       for (pos = 0; pos < bytes_read && lines < d_lines; pos++)
  2043.         if (read_buffer[pos] == 0x0a)
  2044.         { lines++;
  2045.           fpos = i + pos + 1;
  2046.         }
  2047.     }
  2048.     for (pos = 0; pos + lines < text->lines; pos++)
  2049.       strcpy (text->page[pos], text->page[pos + lines]);
  2050.     fpos = start_f_pos;
  2051.     pos = text->lines - lines;
  2052.     do
  2053.     { fseek (f, fpos, SEEK_SET);
  2054.       bytes_read = fread (read_buffer, 1, 4096, f);
  2055.       p = read_buffer;
  2056.       left = bytes_read;
  2057.       while (1)
  2058.       { for (i = 0; i < left && p[i] != 0x0a; i++)
  2059.           ;
  2060.         if (i == left)
  2061.           break;
  2062.         p[i] = 0;
  2063.         if (i > 0 && p[i - 1] == 0x0d)
  2064.           p[i - 1] = 0;
  2065.         strncpy (text->page[pos], p, STRI_LEN);
  2066.         p += i + 1;
  2067.         left -= i + 1;
  2068.         pos++;
  2069.         if (pos == text->lines)
  2070.           break;
  2071.       }
  2072.       fpos += bytes_read - left;
  2073.     } while (pos < text->lines && bytes_read == 4096);
  2074.     return (lines);
  2075.   }
  2076.   return (0);
  2077. }
  2078. /* ---------------------------------------------------------------------- */
  2079. static int
  2080. file_win (char *fname, int user_width, int user_height)
  2081. { WIN_TEXT text;
  2082.   int x, y, i, width, height, not_done = 1, key, len;
  2083.   int start_line = 0, pos = 0, textoffset = 0;
  2084.   char *window_save;
  2085.   int cache_lines, read_lines, file_pos;
  2086.   FILE *f;
  2087.  
  2088.   if (user_height > rows - 1)
  2089.     height = rows - 1;
  2090.   else
  2091.     height = user_height;
  2092.   init_text (&text, fname);
  2093.   window_save = open_win (user_width, height, screen_attr_ffocus,
  2094.               single_border, &x, &y, &width, text.tittle);
  2095.   height -= 1;
  2096.   cache_lines = height * 2;
  2097.   f = init_win_file (&text, fname, height * 3, &file_pos);
  2098.   if (!f)
  2099.     return (0);
  2100.   while (not_done)
  2101.   {
  2102.     screen_attr = screen_attr_normal;
  2103.     for (i = 0; i <= height; i++)
  2104.     {
  2105.       if (i + start_line < text.lines)              
  2106.       { len = strlen (text.page[i + start_line]);
  2107.     putl (x, y + i, width, text.page[i + start_line] + 
  2108.               ((textoffset < len) ? textoffset : len));
  2109.       } else
  2110.     putl (x, y + i, width , " ");
  2111.     }
  2112.     screen_attr = screen_attr_focus;
  2113.     len = strlen (text.page[pos + start_line]);
  2114.     putl (x, y + pos, width, text.page[pos + start_line] + 
  2115.           ((textoffset < len) ? textoffset : len));
  2116.     refresh ();
  2117.     key = getykey ();
  2118.     if (key == K_Escape)
  2119.     { switch (key = getykey ())
  2120.       { case 'v':
  2121.         case 'V':
  2122.           key = K_PageUp;
  2123.           break;
  2124.         case '<':
  2125.           key = K_Home;
  2126.           break;
  2127.         case '>':
  2128.           key = K_End;
  2129.           break;
  2130.         case K_Escape:
  2131.           key = K_Control_G;
  2132.           break;
  2133.         default:
  2134.           key = 0;
  2135.           break;
  2136.       }
  2137.     }           
  2138.     if (key == K_Control_X)
  2139.     { switch (key = getykey ())
  2140.       { case K_Control_W:
  2141.           write_log (x, y, x + width, y + height);
  2142.           break;
  2143.         case '<':
  2144.           textoffset++;
  2145.           break;
  2146.         case '>':
  2147.           if (textoffset)
  2148.             textoffset--;
  2149.           break;
  2150.       } 
  2151.       key = 0;
  2152.     }
  2153.     switch (key)
  2154.     {
  2155.       case K_Up:
  2156.       case K_EUp:
  2157.       case K_Left:
  2158.       case K_ELeft:
  2159.       case K_Control_P:
  2160.       case K_Control_B:
  2161.     if (pos == 0)
  2162.     { if (start_line)
  2163.         start_line--;
  2164.           else
  2165.           { read_lines = read_win_file (&text, f, -cache_lines, &file_pos);
  2166.             if (read_lines)
  2167.               start_line += read_lines - 1;
  2168.           }
  2169.     }
  2170.     else
  2171.       pos--;
  2172.     break;
  2173.       case K_Down:
  2174.       case K_EDown:    
  2175.       case K_Right:
  2176.       case K_ERight:
  2177.       case K_Control_N:
  2178.       case K_Control_F:
  2179.     if (pos < height)
  2180.     { if (start_line + pos < text.lines - 1)
  2181.         pos++;
  2182.           else
  2183.           { read_lines = read_win_file (&text, f, cache_lines, &file_pos);
  2184.             if (read_lines)
  2185.             { start_line -= read_lines - 1;
  2186.               pos++;
  2187.             }
  2188.           }
  2189.     } else
  2190.     { if (start_line + pos < text.lines - 1)
  2191.         start_line++;
  2192.           else
  2193.           { read_lines = read_win_file (&text, f, cache_lines, &file_pos);
  2194.             if (read_lines)
  2195.               start_line -= read_lines - 1;
  2196.           }
  2197.     }
  2198.     break;
  2199.       case K_PageUp:
  2200.       case K_EPageUp:
  2201.         if (start_line <= height - 1)
  2202.         { read_lines = read_win_file (&text, f, -cache_lines, &file_pos);
  2203.           if (read_lines)
  2204.             start_line += read_lines;
  2205.         }
  2206.         if (start_line > height - 1)
  2207.           start_line -= height - 1;
  2208.         else
  2209.           start_line = 0;
  2210.         break;
  2211.       case K_PageDown:
  2212.       case K_EPageDown:
  2213.       case K_Control_V:
  2214.         if (start_line >= text.lines - height - 1)
  2215.         { read_lines = read_win_file (&text, f, cache_lines, &file_pos);
  2216.           if (read_lines)
  2217.             start_line -= read_lines;
  2218.         }
  2219.         if (start_line < text.lines - height - 1)
  2220.           start_line += height - 1;
  2221.         if (start_line >= text.lines - height - 1)
  2222.         { read_lines = read_win_file (&text, f, cache_lines, &file_pos);
  2223.           if (read_lines)
  2224.             start_line -= read_lines;
  2225.         }
  2226.         if (pos + start_line >= text.lines - 1)
  2227.           pos = text.lines - start_line - 1;
  2228.         break;
  2229.       case K_Home: 
  2230.       case K_EHome:
  2231.         start_line = 0;
  2232.         pos = 0;
  2233.         break;
  2234.       case K_End:  
  2235.       case K_EEnd:
  2236.         if (start_line + height < text.lines - 1)
  2237.         { start_line = text.lines - height - 1;
  2238.           pos = text.lines - start_line - 1;
  2239.         }
  2240.         break;
  2241.       case K_Return:
  2242.       case K_Control_G:
  2243.     not_done = 0;
  2244.     }
  2245.   }
  2246.   close_win (window_save);
  2247.   free_text (&text);
  2248.   fclose (f);
  2249.   return (1);
  2250. }
  2251. /* ---------------------------------------------------------------------- */
  2252. void 
  2253. read_log ()
  2254. { if (0 == 1)   /* Or memory == oo */
  2255.   { old_read_log ();
  2256.     return;
  2257.   }
  2258.   if (!filename)
  2259.     if (my_read_string("Enter filename: "))
  2260.       return;
  2261.     else
  2262.       filename = strdup(read_buffer);
  2263.   if (!file_win (filename, cols - 2, rows - 2))
  2264.   { message(CL_Error,"Cannot open file %s",filename);
  2265.     free (filename);
  2266.     filename = 0;
  2267.   }
  2268. }
  2269. /* ---------------------------------------------------------------------- */
  2270. void
  2271. read_write_log (int x1, int y1, int x2, int y2)
  2272. { int key = my_get_char ("Read or write? (r/w): ");
  2273.   if ((key == 'W') || (key == 'w'))
  2274.   { if (!filename)
  2275.       if (my_read_string("Enter filename: "))
  2276.          return;
  2277.       else
  2278.          filename = strdup(read_buffer);
  2279.     else
  2280.       if (!read_string (filename))     
  2281.       { free (filename);
  2282.         filename = strdup (read_buffer);
  2283.       }
  2284.     write_log (x1, y1, x2, y2);
  2285.   } else
  2286.   { if (!filename)
  2287.       if (my_read_string("Enter filename: "))
  2288.         return;
  2289.       else
  2290.         filename = strdup(read_buffer);
  2291.     else
  2292.       if (!read_string (filename))     
  2293.       { free (filename);
  2294.         filename = strdup (read_buffer);
  2295.       }
  2296.     read_log ();
  2297.   }
  2298. }
  2299. /* ---------------------------------------------------------------------- */
  2300. void
  2301. init_color (int color)
  2302. { if (color)
  2303.   {  screen_attr_normal   = (A_grey  << 4) + A_blue;
  2304.      screen_attr_source   = (A_grey  << 4) + A_black;
  2305.      screen_attr_focus    = (A_blue  << 4) + A_white;
  2306.      screen_attr_ffocus   = (A_cyan  << 4) + A_white;
  2307.      screen_attr_break    = (A_red   << 4) + A_white;
  2308.      screen_attr_message  = (A_green << 4) + A_white;
  2309.      screen_attr_error    = (A_red   << 4) + A_white;
  2310.      screen_attr_resize   = (A_grey  << 4) + A_green;
  2311.      screen_attr_asm      = (A_grey  << 4) + A_brown;
  2312.      screen_attr_help     = (A_grey  << 4) + A_yellow;
  2313.      screen_attr_addr     = (A_grey  << 4) + A_bold + A_black;
  2314.      screen_attr_hot      = (A_grey  << 4) + A_red;
  2315.      screen_attr_button   = (A_green << 4) + A_black;
  2316.      screen_attr_dfocus   = (A_green << 4) + A_yellow;
  2317.   } else
  2318.   {  screen_attr_normal   = (A_black << 4) + A_grey;
  2319.      screen_attr_source   = screen_attr_normal;
  2320.      screen_attr_focus    = (A_grey  << 4) + A_black;
  2321.      screen_attr_ffocus   = (A_grey  << 4) + A_black;
  2322.      screen_attr_break    = (A_black << 4) + A_white;
  2323.      screen_attr_message  = (A_grey  << 4) + A_white;
  2324.      screen_attr_error    = (A_grey  << 4) + A_black;
  2325.      screen_attr_resize   = (A_grey  << 4) + A_black;
  2326.      screen_attr_asm      = screen_attr_normal;
  2327.      screen_attr_help     = screen_attr_normal;
  2328.      screen_attr_addr     = screen_attr_normal;
  2329.      screen_attr_hot      = screen_attr_break;
  2330.      screen_attr_button   = screen_attr_normal;
  2331.      screen_attr_dfocus   = screen_attr_focus;
  2332.   }
  2333.   st_ln_attr = screen_attr_message;
  2334. }
  2335. /* ---------------------------------------------------------------------- */
  2336. void
  2337. init_io (int com_port)
  2338. { int screen_mode;
  2339.  
  2340.   using_com_port_num = com_port;
  2341.   my_line = malloc (4096);                          
  2342.   small_line = malloc (40);
  2343.  
  2344.   max_cols = 80;
  2345.   max_rows = 50;
  2346.   if (using_com_port_num)
  2347.   {
  2348.     cols = 80;
  2349.     rows = 24;
  2350.     com_init (using_com_port_num);
  2351.     screen_mode = 3;                   
  2352.   }
  2353.   else
  2354.   { screen_mode = ScreenMode ();
  2355.     max_cols = ScreenCols ();
  2356.     max_rows = ScreenRows ();
  2357.     cols = max_cols;
  2358.     rows = max_rows;
  2359.   }
  2360.   if (cols < 80 || rows < 24)
  2361.     {
  2362.       fprintf (stderr, "\nDebugger error:\n\
  2363. There are only %d columns and %d rows\n\
  2364. in this display mode.\n\
  2365. The debugger needs at least\n\
  2366. 80 columns and 24 rows.\n",
  2367.            cols, rows);
  2368.       exit (1);
  2369.     }
  2370.   read_buffer = malloc (4096);
  2371.  
  2372.   transfer_screen_save = 0;
  2373.   transfer_screen_save = get_screen ();
  2374.   transfer_screen_save[1] = transfer_screen_save[2] = 0;
  2375.  
  2376.   switch (screen_mode)
  2377.     {
  2378.     case 2:
  2379.     case 7:
  2380.       /* Mono */
  2381.       init_color (0);
  2382.       break;
  2383.     default:
  2384.       /* Colour */
  2385.       init_color (1);
  2386.     }
  2387. }
  2388. /* ---------------------------------------------------------------------- */
  2389. void
  2390. re_init_io (int com_port, int new_rows, int new_cols)
  2391. {
  2392.   cols = new_cols;
  2393.   rows = new_rows;
  2394.  
  2395.   if (using_com_port_num)
  2396.     com_done();
  2397.  
  2398.   if (com_port)
  2399.   { using_com_port_num = com_port;
  2400.     com_init(using_com_port_num);
  2401.     first_transfer = 1;
  2402.     if (cols > max_cols)
  2403.        cols = max_cols;
  2404.     if (rows > max_rows)
  2405.       rows = max_rows;
  2406.   }
  2407.   free (transfer_screen_save);
  2408.   transfer_screen_save = 0;
  2409.   transfer_screen_save = get_screen ();
  2410.   transfer_screen_save[1] = transfer_screen_save[2] = 0; 
  2411.   first_transfer = 1;
  2412. }
  2413. /* ---------------------------------------------------------------------- */
  2414.